﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using EasyComm.Utilities;

namespace EasyComm.Base.Hosting
{
    public class EasyCommServiceHostBase : ServiceHost
    {
        private Type _serviceType;
        private Type[] _serviceContractList;
        private bool _udpAnnouncement;
        private bool _useMEX;
        private bool _debug;
        private string _ns;

        public Uri[] DiscoveryProxyAddresses { get; private set; }
        public ServiceContractCollection Contracts { get; private set; }
        public bool HasContracts { get { return Contracts != null && Contracts.Count > 0; } }

        public virtual Uri ListenUri { get; private set; }

        public EasyCommServiceHostBase(Type serviceType, Type[] serviceContractList, Uri[] discoveryProxyAddresses, bool udpAnnouncement = true, bool useMex = true, bool debug = true, string ns = "http://www.tempuri.org/", params Uri[] baseAddresses)
        {
            _serviceType = serviceType;
            _serviceContractList = serviceContractList;
            _udpAnnouncement = udpAnnouncement;
            _useMEX = useMex;
            _debug = debug;
            _ns = ns;
            DiscoveryProxyAddresses = discoveryProxyAddresses;
            if (baseAddresses == null || baseAddresses.Length == 0)
            {
                baseAddresses = new Uri[] { NetUtils.GetAvailableLocalEndPoint(string.Format("{0}_EndpointUrl", serviceType.Name), string.Format("{0}/", serviceType.Name), ProtocolScheme.Tcp) };
            }
            base.InitializeDescription(serviceType, new UriSchemeKeyedCollection(baseAddresses));
            SetContracts();
        }

        protected override void ApplyConfiguration()
        {
            ListenUri = EasyComm.Hosting.Configuration.GenericConfiguration.ApplyConfiguration(this, _serviceType, _serviceContractList, DiscoveryProxyAddresses, _udpAnnouncement, _useMEX, _debug, _ns);
            base.ApplyConfiguration();
        }

        private void SetContracts()
        {
            Contracts = new ServiceContractCollection();
            if (_serviceContractList == null)
            {
                return;
            }
            foreach (ServiceEndpoint endpoint in base.Description.Endpoints)
            {
                bool canAdd = false;

                if (endpoint.Contract.Name == "DiscoveryProxy" ||
                    endpoint.Contract.Name == "IRequestReplyRouter")
                {
                    foreach (Type contract in _serviceContractList)
                    {
                        Contracts.Add(new ServiceContract(contract, endpoint.Address.Uri));
                        continue;
                    }
                }
                else
                {
                    foreach (Type contract in _serviceContractList)
                    {
                        if (endpoint.Name.EndsWith(string.Format("_{0}", contract.Name.Replace(".", "-"))))
                        {
                            canAdd = true;
                            break;
                        }
                    }
                }

                if (canAdd)
                {
                    Contracts.Add(new ServiceContract(endpoint.Contract.ContractType, endpoint.Address.Uri));
                }
            }
        }
    }
}
